package com.googlecode.geoteacher.logic;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.graphics.Color;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.google.maps.android.SphericalUtil;

public class Match {

	private ChallengeFile file;

	private List<PlaceWrapper> places = new ArrayList<PlaceWrapper>();

	private int currentPlace = -1;

	private Object solutionUI;
	private Marker userClickedMarker;
	private Polyline solutionLine;

	public Match(ChallengeFile file, int numOfPlaces) {
		this.file = file;

		List<Place> challengePlaces = new ArrayList<Place>();

		for (Place place : file.getPlaces()) {
			if (place.isChallenge()) {
				challengePlaces.add(place);
			}
		}

		Collections.shuffle(challengePlaces);

		for (int i = 0; i < numOfPlaces; i++) {
			places.add(new PlaceWrapper(challengePlaces.get(i)));
		}
	}

	public void displayPermanent(GoogleMap map) {
		for (Place place : file.getPlaces()) {
			if (place.isDisplay()) {
				place.displayPermanent(map);
			}
		}
	}

	public Place nextPlaceAndHideLastSolution(GoogleMap map) {

		if (solutionUI != null) {
			places.get(currentPlace).place.removeSolution(solutionUI);
			solutionUI = null;
		}

		if (userClickedMarker != null) {
			userClickedMarker.remove();
			userClickedMarker = null;
		}

		if (solutionLine != null) {
			solutionLine.remove();
			solutionLine = null;
		}

		currentPlace++;
		return places.get(currentPlace).place;
	}

	public Place getCurrentPlace() {
		return places.get(currentPlace).place;
	}

	public double saveResultAndShowSolution(LatLng position, GoogleMap map) {
		double distance = 0;

		if (position == null) {
			places.get(currentPlace).timeElapsed = true;
		} else {
			LatLng closestPoint = places.get(currentPlace).place
					.closestPointTo(position);

			if (closestPoint != null) {
				distance = SphericalUtil.computeDistanceBetween(closestPoint,
						position);

				solutionLine = map.addPolyline(new PolylineOptions()
						.add(position).add(closestPoint).color(Color.RED)
						.geodesic(true));
			}

			places.get(currentPlace).distance = distance;
		}

		solutionUI = places.get(currentPlace).place.displaySolution(map);

		if (position != null) {
			userClickedMarker = map.addMarker(new MarkerOptions().position(
					position).icon(
					BitmapDescriptorFactory
							.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
		}

		return distance;
	}

	private static class PlaceWrapper {
		public final Place place;
		public double distance;
		public boolean timeElapsed = false;

		public PlaceWrapper(Place place) {
			this.place = place;
		}
	}

	public int getAvgDist() {
		if (places.size() == 0) {
			return -1;
		}

		double sum = 0;
		int count = 0;

		for (PlaceWrapper p : places) {
			if (!p.timeElapsed) {
				sum += p.distance;
				count++;
			}
		}

		return (int) (sum / count / 1000);
	}

	public String[] getPlacesArray() {
		String[] arr = new String[places.size()];

		for (int i = 0; i < places.size(); i++) {
			arr[i] = places.get(i).place.getName();
		}

		return arr;
	}

	public int[] getDistancesArray() {
		int[] distances = new int[places.size()];

		for (int i = 0; i < places.size(); i++) {
			distances[i] = (int) (places.get(i).distance / 1000);
		}

		return distances;
	}
}